package com.spring.aop;

import com.spring.annotation.Transactional;

import java.lang.reflect.*;
import java.util.Arrays;

public class TransactionHandler implements InvocationHandler {
    private TransactionManager transactionManager;

    private Object object;

    public TransactionHandler(Object object) {
        this.object = object;
    }

    public TransactionHandler(Object object, TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
        this.object = object;
    }

    public Object getProxy() {
        Object proxyInstance = Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(), this);
        return proxyInstance;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        Transactional annotation = object.getClass().getAnnotation(Transactional.class);
//        Transactional annotation1 = method.getAnnotation(Transactional.class);
        Method[] methods = object.getClass().getDeclaredMethods();
        long count =
                Arrays.stream(methods).filter(m -> m.getAnnotation(Transactional.class) != null && m.getName().equals(method.getName())).count();
        if (count > 0 || annotation != null) {
            return active(object, method, args);
        } else {
            Object invoke = null;
            try {
                invoke = method.invoke(object, args);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            return invoke;
        }
    }

    private Object active(Object object, Method method, Object[] args) {
        Object result = null;
        // 开启事务
        transactionManager.OpenTheTransaction();
        try {
            // 执行业务逻辑
            result = method.invoke(object, args);

            // 事务提交
            transactionManager.commitTransaction();
        } catch (Exception e) {
            e.printStackTrace();
            // 事务回滚
            transactionManager.rollback();
            throw new RuntimeException();
        }
        return result;
    }
}
